﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Jamhee.Noctiluca.Common;

namespace Jamhee.Noctiluca.LightWiki.Markup
{
    class WikiMarkupParser
    {
        #region Variables

        private MarkupStack _stack = new MarkupStack();
        private IMarkup[] _markups;
        private Header _header = new Header();
        private HorizoneLine _horizoneLine = new HorizoneLine();
        private Bold _bold = new Bold();
        private Italic _italic = new Italic();
        private Image _image = new Image();
        private Link _link = new Link();
        private List _list = new List();

        #endregion

        #region Constants


        #endregion

        public WikiMarkupParser()
        {
            _markups = new IMarkup[] { _header, _horizoneLine, _bold, 
                _italic, _image, _link, _list};
        }


        #region Stack

        public void ClearStack()
        {
            _stack.Clear();
        }

        #endregion

        public string Parse(string wikiMarkup, string docFolder, Uri url)
        {
            bool addP = true;
            string html = wikiMarkup;
            string prefix = "";

            // Check the stack flag to see if any special handling is requried
            IMarkupStackFlag lastStack = _stack.Pop();
            if (lastStack != null)
            {
                if (lastStack is ListStackFlag)
                {
                    if (_list.IsMatch(wikiMarkup))
                    {
                        // If current input is also List Markup, we will put the stack back
                        _stack.Push(lastStack);
                    }
                    else
                    {
                        // If current input is NOT List Markup, we need to clear all of the List Stack Flags
                        // and add the ending html mark up, until we get a different type
                        int lastLevel = -1;
                        while (lastStack != null && lastStack is ListStackFlag)
                        {
                            ListStackFlag listStack = (ListStackFlag)lastStack;
                            
                            string temp = "";

                            if (listStack.Type == ListStackFlag.ListType.ORDERED)
                            {
                                temp = "</ol>";
                            }
                            else if (listStack.Type == ListStackFlag.ListType.UNORDERED)
                            {
                                temp = "</ul>";
                            }

                            for (int xx = 0; xx < listStack.Level - lastLevel; xx++)
                            {
                                prefix += temp;
                            }

                            lastLevel = listStack.Level;
                            lastStack = _stack.Pop();
                        }

                        // We will put the stack back because it's not List Stack Flag
                        if (lastStack != null)
                        {
                            _stack.Push(lastStack);
                        }
                    }
                }
            }

            // Parse the wiki markup
            IMarkup markup = null;
            for (int i = 0; i < _markups.Length; i ++)
            {
                markup = _markups[i];

                if (markup.IsMatch(wikiMarkup))
                {
                    html = markup.ParseMarkup(html, docFolder, url, _stack);
                    addP = addP && markup.AddParagraphMarkup;
                }
            }

            if (addP)
            {
                html += "<p>";
            }

            // Add prefix and return
            return prefix + html;
        }

    }
}
